﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Collections.ObjectModel;
namespace Tracy.CoreLib.Data
{

    /// <summary>
    /// 含有唯一ID的XmlModel
    /// </summary>
    public abstract class ManagedXmlModel_CommonFunctions : XmlModel_AutoParseFunctions
    {
        #region 构造函数
        public ManagedXmlModel_CommonFunctions() : base() { }
        public ManagedXmlModel_CommonFunctions(string xml) : base(xml) { }
        public ManagedXmlModel_CommonFunctions(XmlNode node) : base(node) { }
        #endregion
        protected int id = -1;
        /// <summary>
        /// 返回XmlModel的ID，-1表示ID尚未设置
        /// </summary>
        public int Id
        {
            get { return id; }
            set
            {
                if (id != value)
                {
                    if (id == -1)
                    {
                        id = value;
                        Data[Constants.CONST_TAG_ID] = value.ToString();
                    }
                    else
                    {
                        //ID只能设定一次
                        throw new TracyException(TracyException.EXCEPTION_ID_ALREADY_SET);
                    }
                }
            }
        }

        ///// <summary>
        ///// 加载Xml
        ///// </summary>
        ///// <param name="node"></param>
        //public override void LoadXml(XmlNode node)
        //{
        //    base.LoadXml(node);
            
        //}

        protected override void ParseXml(XmlNode node)
        {
            Id = Convert.ToInt32(SelectNode(node, Constants.CONST_TAG_ID, true).InnerText);
            base.ParseXml(node);
        }

        ///// <summary>
        ///// 导出为Xml
        ///// </summary>
        ///// <param name="doc">Xml节点所基于的XmlDocument</param>
        //public override XmlNode ToXmlNode(XmlDocument doc)
        //{
        //    XmlNode newNode =  base.ToXmlNode(doc);
        //    AppendTextChildNode(doc, newNode, Constants.CONST_TAG_ID, id.ToString());
        //    return newNode;
        //}
    }

    /// <summary>
    /// XmlModel的容器
    /// </summary>
    public abstract class XmlModelContainer_CommonFunctions : XmlModel_AutoParseFunctions
    {   
        #region 构造函数
        public XmlModelContainer_CommonFunctions() { }
        public XmlModelContainer_CommonFunctions(string xml): base(xml){ }
        public XmlModelContainer_CommonFunctions(XmlNode node) : base(node) { }
        #endregion

        protected IXmlModelCollection items;
        /// <summary>
        /// 所含XmlModelItem的集合
        /// </summary>
        public virtual IXmlModelCollection Items
        {
            get
            {
                if (items == null) items = new XmlModelCollection();
                return items;
            }
        }

        /// <summary>
        /// 默认的子节点标签名
        /// </summary>
        public virtual string XmlChildNodeName
        {
            get
            {
                return Constants.CONST_TAG_ITEM;
            }
        }
 
        /// <summary>
        /// 加载Xml
        /// </summary>
        /// <param name="node">Xml节点</param>
        public override void LoadXml(XmlNode node)
        {
            if (this is IXmlModelContainer)
            {
                if (node.Name != ((IXmlModelContainer)this).XmlNodeName)//该节点的标签
                {
                    node = SelectNode(node, ((IXmlModelContainer)this).XmlNodeName, true);
                }

                //导入子节点
                XmlNodeList itemlist = SelectNodes(node, ((IXmlModelContainer)this).XmlChildNodeName);
                foreach (XmlNode itemNode in itemlist)
                {
                    AddItem(itemNode);
                }

                PreParseXml(node); //子类的额外逻辑

                GeneralImportData(node); //通用导入函数
            }
            else
            {
                throw new TracyException("未实现接口IXmlModelContainer");
            }
        }

        /// <summary>
        /// 导出为Xml节点
        /// </summary>
        /// <param name="doc">Xml节点所基于的XmlDocument</param>
        public override XmlNode ToXmlNode(XmlDocument doc)
        {
            if (this is IXmlModelContainer)
            {
                XmlNode newNode = doc.CreateElement(((IXmlModelContainer)this).XmlNodeName);//该节点的标签
                //导出子节点
                foreach (XmlModel_AutoParseFunctions item in Items)
                {
                    newNode.AppendChild(item.ToXmlNode(doc));
                }

                GeneralExportData(doc, newNode);//通用导出函数

                PostGenerateXml(doc, newNode);//子类的额外逻辑
                return newNode;
            }
            else
            {
                throw new TracyException("未实现接口IXmlModelContainer");
            }
        }

        /// <summary>
        /// 添加项目
        /// </summary>
        /// <param name="newItem">含有唯一键的XmlModel</param>
        public virtual void AddItem(IXmlModelItem newItem)
        {
            if (newItem != null)
            {
                Items.Add(newItem);
            }
        }

        /// <summary>
        /// 添加项目（通过Xml节点生成新的XmlModelItem）
        /// </summary>
        /// <param name="node">Xml节点</param>
        /// <returns></returns>
        public virtual IXmlModelItem AddItem(XmlNode node)
        {
            if (node != null)
            {
                if (this is IXmlModelContainer)
                {
                    IXmlModelItem newItem = ((IXmlModelContainer)this).GenerateChild(node);
                    AddItem(newItem);
                    return newItem;
                }
                else
                {
                    throw new TracyException("该类未实现IXmlModelContainer接口");
                }
            }
            else return null;
        }

        /// <summary>
        /// 移除项目
        /// </summary>
        /// <param name="oldItem">含有唯一键的XmlModel</param>
        public virtual void RemoveItem(IXmlModelItem oldItem)
        {
            if (oldItem != null)
            {
                Items.Remove(oldItem);
            }
        }
    }

    /// <summary>
    /// XmlModel提供者
    /// </summary>
    public abstract class XmlModelProvider_CommonFunctions : XmlModelContainer_CommonFunctions
    {
        #region 构造函数
        public XmlModelProvider_CommonFunctions() { }
        public XmlModelProvider_CommonFunctions(string xml): base(xml){ }
        public XmlModelProvider_CommonFunctions(XmlNode node) : base(node) { }
        #endregion

        protected int largestId = -1;
        /// <summary>
        /// 所有ID中的最大值
        /// </summary>
        public int LargestId
        {
            get
            {
                if (largestId != -1) return largestId;//-1则重新计算
                else
                {
                    int currentLargestId = -1;
                    foreach (IManagedXmlModelItem item in Items)
                    {
                        if (item.Id > currentLargestId) currentLargestId = item.Id;
                    }
                    return currentLargestId;
                }
            }
        }

        /// <summary>
        /// 所含ManagedXmlModelItem的集合
        /// </summary>
        public override IXmlModelCollection Items
        {
            get
            {
                if (items == null) items = new ManagedXmlModelCollection();
                return items;
            }
        }

        /// <summary>
        /// 添加项目
        /// </summary>
        /// <param name="newItem">含有ID和唯一键的XmlModel</param>
        public virtual void AddItem(IManagedXmlModelItem newItem)
        {
            
            if (newItem.Id == -1)//如果ID尚未指定
            {
                newItem.Id = LargestId + 1;
                largestId = newItem.Id;
            }
            else//最大ID需要重新计算
            {
                largestId = -1;
            }
            AddItem((IXmlModelItem)newItem);
            //Items.Add(newItem);
        }

        public virtual IManagedXmlModelItem GetItemById(int id)
        {
            return ((IManagedXmlModelCollection)Items).GetItemById(id);
        }
    }
}
